package com.yhd.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.yhd.entity.TCourseBooked;
import com.yhd.entity.TUser;
import com.yhd.entity.dto.CourseBookedDto;
import com.yhd.entity.dto.UserCountDto;
import com.yhd.entity.dto.UserDto;
import com.yhd.entity.query.CourseBookedVO;
import com.yhd.entity.query.UserVO;
import com.yhd.entity.query.WxVO;
import com.yhd.entity.result.ResultVo;
import com.yhd.mapper.CourseBookedMapper;
import com.yhd.mapper.UserMapper;
import com.yhd.model.PageInfo;
import com.yhd.model.ResultPage;
import com.yhd.service.BaseService;
import com.yhd.service.CourseService;
import com.yhd.service.UserService;
import com.yhd.utils.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Transactional(rollbackFor = Exception.class)
@Service
public class UserServiceImpl extends BaseService<UserMapper, TUser> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private CourseService courseService;
    @Autowired
    private CourseBookedMapper courseBookedMapper;
    
    @Override
    public UserDto login(UserVO userVO) {
        TUser tUserQ = new TUser();
        tUserQ.setLoginId(userVO.getLoginId());
        tUserQ.setPassword(userVO.getPassword());
        tUserQ.setType(userVO.getType());
        //状态 1:生效 0:已删除  2:已冻结
        tUserQ.setStatus(1);
        TUser tUser = userMapper.selectOne(tUserQ);
        if (null != tUser){
            UserDto userDto = new UserDto();
            BeanUtils.copyProperties(tUser, userDto);
            return userDto;
        }
        return null;
    }

    @Override
    public UserDto selectUserById(String id) {
        UserDto userDto = new UserDto();
        TUser user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            return null;
        }
       
        BeanUtils.copyProperties(user, userDto);
        //查询关联的邀请人
        if (null != user.getInvitedCode()){
            TUser tUser = new TUser();
            tUser.setInvitationCode(user.getInvitedCode());
            tUser = userMapper.selectOne(tUser);
            if (tUser != null) {
                UserDto invitedUser = new UserDto();
                BeanUtils.copyProperties(tUser, invitedUser);
                userDto.setInvitedUser(invitedUser);
            }
        }
        //订单信息
        List<UserCountDto> counts = courseService.selectCountByUsers(Arrays.asList(user.getId()));
        Map<String, List<UserCountDto>> typeMap = counts.stream().collect(Collectors.groupingBy(val -> val.getType()));
        List<UserCountDto> activityCounts = typeMap.get("activity");
        List<UserCountDto> courseCounts = typeMap.get("course");
        Map<String, Integer> activityMap = null;
        if (!CollectionUtils.isEmpty(activityCounts)) {
            activityMap  = activityCounts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
        }
        Map<String, Integer> courseMap = null;
        if (!CollectionUtils.isEmpty(courseCounts)) {
            courseMap = courseCounts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
        }
        Map<String, DoubleSummaryStatistics> summaryStatisticsMap = counts.stream().collect(Collectors.groupingBy(val -> val.getUserId(),
                Collectors.summarizingDouble(u -> u.getSumPrice().doubleValue())));
    
        List<UserCountDto> abouts = courseService.countUserAbout(Arrays.asList(user.getId()));
        Map<String, Integer> aboutMap = abouts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
        if (!CollectionUtils.isEmpty(activityMap)) {
            userDto.setActivityOrderNum(activityMap.get(userDto.getId()));
        }
        if (!CollectionUtils.isEmpty(courseMap)) {
            userDto.setCourseOrderNum(courseMap.get(userDto.getId()));
        }
        if (!CollectionUtils.isEmpty(aboutMap)) {
            userDto.setAboutNum(aboutMap.get(userDto.getId()));
        }
        DoubleSummaryStatistics summaryStatistics = summaryStatisticsMap.get(userDto.getId());
        userDto.setOrderTotalPrice(summaryStatistics == null ? 0 : summaryStatistics.getSum());
        //查询邀请用户数和销售课程数
        TUser userParam = new TUser();
        userParam.setInvitedCode(userDto.getInvitationCode());
        userDto.setInvitedUserNum(userMapper.selectCount(userParam));
        Example bookeExample = new Example(TCourseBooked.class);
        bookeExample.createCriteria().andEqualTo("referrerUser", userDto.getInvitationCode())
                .andEqualTo("type", "course").andNotEqualTo("subType", 1).andEqualTo("status",2);
        userDto.setSaleCourseNum(courseBookedMapper.selectCountByExample(bookeExample));
        return userDto;
       
    }

    @Override
    public String getOpenId(String wxcode) {
        String wxInfo =  WeixinCommonUtil.getAuthByCode(WeixinCommonUtil.WX_APPID,WeixinCommonUtil.WX_APPSECRET,wxcode);
        System.out.println("微信登录返回信息：resultInfo = " + wxInfo);
        JSONObject jsonObject = JSONObject.parseObject(wxInfo);
        int errCode = jsonObject.getIntValue("errcode");
        String errMsg = jsonObject.getString("errmsg");
        if (errCode == 0){
            //得到微信用户ID
            String openid = jsonObject.getString("openid");
            if (!"".equals(openid)){
                String session_key = jsonObject.getString("session_key");
                redisUtils.set("wxlogin_" + openid, session_key,604800L);
                return openid;
            }
        }
        System.out.println("获取openid信息1："+ errMsg);
        return "errcode：" + errCode + "errmsg：" + errMsg;
    }

    @Override
    public String getWxPhone(WxVO wxVO) {
        String session_key = (String) redisUtils.get("wxlogin_" + wxVO.getOpenId());
        System.out.println(">>>>>>>获取wxlogin_>>>>>>>>"+ wxVO.getOpenId() + ">>>>" + session_key);
        //解密敏感信息
        String phoneInfo = null;
        try {
            phoneInfo = WeixinCommonUtil.decrypt(wxVO.getEncryptedData(), wxVO.getIv(), session_key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(phoneInfo);
        if (null != phoneInfo && !"".equals(phoneInfo)){
            //获取手机号
            JSONObject jsonObject = JSONObject.parseObject(phoneInfo);
            String phoneNumber = jsonObject.getString("phoneNumber");
            if (null != phoneNumber && !"".equals(phoneNumber)){
                return phoneNumber;
            }
        }
        return null;
    }

    /**
     * 小程序系统登陆
     * @param userVO
     * @return
     */
    @Override
    public UserDto customerLogin(UserVO userVO) {
        if (null != userVO){
            //两者必有其一
            if (null == userVO.getPhone() || "".equals(userVO.getPhone())
                    || null == userVO.getOpenId() || "".equals(userVO.getOpenId())){
                return null;
            }
        }
        userVO.setType("customer");
        UserDto userDto = userMapper.selectUserByOpenIdOrPhone(userVO);
        if (null == userDto){
            //手机号不能重复
            UserVO userVO2 = new UserVO();
            userVO2.setPhone(userVO.getPhone());
            userVO2.setType("customer");
            UserDto userDto1 = userMapper.selectUserByOpenIdOrPhone(userVO2);
            if (null != userDto1){
                //如果手机号存在则更新openid
                //如果手机号已绑定openid则不更新
                if (null != userDto1.getOpenId() && !"".equals(userDto1.getOpenId())){
                    if (!userVO.getOpenId().equals(userDto1.getOpenId())){
                        UserDto userDto2 = new UserDto();
                        userDto2.setState(-1);
                        return userDto2;
                    }
                }else {
                    //手机号绑定微信openid
                    userDto1.setOpenId(userVO.getOpenId());
                    TUser newTuser = new TUser();
                    BeanUtils.copyProperties(userDto1,newTuser);
                    int updateUser = userMapper.updateByPrimaryKeySelective(newTuser);
                    if (updateUser > 0){
                        return userDto1;
                    }
                }
            }
            //微信号不能重复
            UserVO userVO3 = new UserVO();
            userVO3.setOpenId(userVO.getOpenId());
            userVO3.setType("customer");
            UserDto userDto3 = userMapper.selectUserByOpenIdOrPhone(userVO3);
            if (null != userDto3){
                //如果手机号存在则更新openid
                //如果手机号已绑定openid则不更新
                if (null != userDto3.getPhone() && !"".equals(userDto3.getPhone())){
                    if (!userVO.getPhone().equals(userDto3.getPhone())){
                        UserDto userDto2 = new UserDto();
                        userDto2.setState(-2);
                        return userDto2;
                    }
                }else {
                    //手机号绑定微信openid
                    userDto3.setOpenId(userVO.getOpenId());
                    TUser newTuser = new TUser();
                    BeanUtils.copyProperties(userDto3,newTuser);
                    int updateUser = userMapper.updateByPrimaryKeySelective(newTuser);
                    if (updateUser > 0){
                        return userDto3;
                    }
                }
            }
            //手机号不存在则新增
            //用户不存在新增用户
            TUser tUser = new TUser();
            BeanUtils.copyProperties(userVO,tUser);
            tUser.setId(Utils.getId());
            tUser.setType("customer");
            if (null != tUser.getPhone()){
                tUser.setLoginId(tUser.getPhone());
            }
            try {
                tUser.setPassword(AesUtils.encrypt(AesUtils.DEFAULT_PWS,"abc1234"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            tUser.setCreateTime(new Date());
            tUser.setUpdateTime(new Date());
            tUser.setUserNo(UUID.randomUUID().toString().replace("-", "").substring(0, 16).toUpperCase());
            tUser.setInvitationCode(RandomStringUtils.randomAlphanumeric(6));
            int addUser = userMapper.insertSelective(tUser);
            if (addUser > 0){
                userDto = new UserDto();
                BeanUtils.copyProperties(tUser,userDto);
            }
        }
        return userDto;
    }
    
    /**
     * 修改信息
     * @param userVO
     * @param userInfo
     * @return
     */
    @Override
    public ResultVo<UserDto> updateUser(UserVO userVO, UserDto userInfo) {
        TUser user = new TUser();
        BeanUtils.copyProperties(userVO, user);
        user.setId(userInfo.getId());
        if (!StringUtils.isEmpty(user.getId())) {
            if (null != userVO.getPhone()){
                UserDto userDto1 = userMapper.selectUserByOpenIdOrPhone(userVO);
                if (null != userDto1){
                    TUser olduser = new TUser();
                    olduser.setId(user.getId());
                    olduser = userMapper.selectOne(olduser);
                    if (null != olduser){
                        if (!olduser.getId().equals(userDto1.getId())){
                            return ResultVo.failure("10005","手机号已存在不能修改！");
                        }
                    }
                }
            }
            //修改
            user.setUpdateTime(new Date());
            int updateUser = userMapper.updateByPrimaryKeySelective(user);
            if (updateUser > 0){
                TUser select = new TUser();
                select.setId(userInfo.getId());
                select = userMapper.selectByPrimaryKey(select);
                UserDto result = new UserDto();
                BeanUtils.copyProperties(select, result);
                return ResultVo.success(result);
            }
        }
        return ResultVo.failure("10003","操作失败。");
    }
    
    /**
     * 用户列表
     * @param userVO
     * @return
     */
    @Override
    public ResultPage<List<UserDto>> selectList(UserVO userVO) {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageNum(userVO.getPageNum());
        pageInfo.setPageSize(userVO.getPageSize());
        Example example = new Example(TUser.class);
        Example.Criteria criteria = example.createCriteria().andEqualTo("isDel", 0);
        if (!StringUtils.isEmpty(userVO.getUserName())) {
            criteria.andLike("userName", "%" + userVO.getUserName() + "%");
        }
        if (!StringUtils.isEmpty(userVO.getNickname())) {
            criteria.andEqualTo("nickname","%" + userVO.getNickname() + "%");
        }
        if (!StringUtils.isEmpty(userVO.getInviter())) {
            criteria.andEqualTo("inviter", "%" + userVO.getInviter() + "%");
        }
        if (!StringUtils.isEmpty(userVO.getReferrer())) {
            criteria.andEqualTo("referrer", "%" + userVO.getReferrer() + "%");
        }
        if (!StringUtils.isEmpty(userVO.getPhone())) {
            criteria.andEqualTo("phone", userVO.getPhone());
        }
        if (userVO.getType() != null) {
            criteria.andEqualTo("type", userVO.getType());
        }
        if (userVO.getRole() != null) {
            criteria.andEqualTo("role", userVO.getRole());
        }
        if (userVO.getRegisterStartTime() != null) {
            criteria.andGreaterThanOrEqualTo("createTime", userVO.getRegisterStartTime());
        }
        if (userVO.getRegisterEndTime() != null) {
            criteria.andLessThanOrEqualTo("createTime", userVO.getRegisterStartTime());
        }
        example.setOrderByClause("createTime desc");
        TUser param = new TUser();
        BeanUtils.copyProperties(userVO, param);
        Page<List<UserDto>> result = pageBuild(pageInfo).doSelectPage(() -> {
            List<TUser> list = userMapper.selectByExample(example);
            for (TUser user : list) {
                UserDto userDto = new UserDto();
                BeanUtils.copyProperties(user, userDto);
            }
        });
        ResultPage resultPage = pageTransform(result);
        if (CollectionUtils.isEmpty(resultPage.getData())) {
            return resultPage;
        }
        List<UserDto> data =  BeanMapperUtil.copyList(resultPage.getData(), UserDto.class);
        List<String> userIds = data.stream().map(UserDto::getId).collect(Collectors.toList());
        //订单信息
        List<UserCountDto> counts = courseService.selectCountByUsers(userIds);
        Map<String, List<UserCountDto>> typeMap = counts.stream().collect(Collectors.groupingBy(val -> val.getType()));
        List<UserCountDto> activityCounts = typeMap.get("activity");
        List<UserCountDto> courseCounts = typeMap.get("course");
        Map<String, Integer> activityMap = null;
        if (!CollectionUtils.isEmpty(activityCounts)) {
            activityMap  = activityCounts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
        }
        Map<String, Integer> courseMap = null;
        if (!CollectionUtils.isEmpty(courseCounts)) {
            courseMap = courseCounts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
        }
        Map<String, DoubleSummaryStatistics> summaryStatisticsMap = counts.stream().collect(Collectors.groupingBy(val -> val.getUserId(),
                Collectors.summarizingDouble(user -> user.getSumPrice().doubleValue())));
        //约课
        List<UserCountDto> abouts = courseService.countUserAbout(userIds);
        Map<String, Integer> aboutMap = abouts.stream().collect(Collectors.toMap(UserCountDto::getUserId, val -> val.getCount(), (v1, v2) -> v1));
    
        for (UserDto userDto:data) {
            if (!CollectionUtils.isEmpty(activityMap)) {
                userDto.setActivityOrderNum(activityMap.get(userDto.getId()));
            }
            if (!CollectionUtils.isEmpty(courseMap)) {
                userDto.setCourseOrderNum(courseMap.get(userDto.getId()));
            }
            if (!CollectionUtils.isEmpty(aboutMap)) {
                userDto.setAboutNum(aboutMap.get(userDto.getId()));
            }
            DoubleSummaryStatistics summaryStatistics = summaryStatisticsMap.get(userDto.getId());
            userDto.setOrderTotalPrice(summaryStatistics == null ? 0 : summaryStatistics.getSum());
//            if ("system".equals(userDto.getType())) {
                //查询邀请用户数和销售课程数
                TUser userParam = new TUser();
                userParam.setInvitedCode(userDto.getInvitationCode());
                userDto.setInvitedUserNum(userMapper.selectCount(userParam));

                Example bookeExample = new Example(TCourseBooked.class);
                bookeExample.createCriteria().andEqualTo("referrerUser", userDto.getInvitationCode())
                        .andEqualTo("type", "course").andNotEqualTo("subType", 1);
                userDto.setSaleCourseNum(courseBookedMapper.selectCountByExample(bookeExample));
//            }
        }
        resultPage.setData(data);
        return resultPage;
    }
    
    /**
     * 删除用户
     * @param userVO
     */
    @Override
    public void deleteUser(UserVO userVO) {
        if (StringUtils.isEmpty(userVO.getId())) {
            return;
        }
        TUser user = new TUser();
        user.setId(userVO.getId());
        user.setIsDel(1);
        userMapper.updateByPrimaryKeySelective(user);
    }
    
    /**
     * 保存用户
     * @param userVO
     * @return
     */
    @Override
    public ResultVo<UserDto> saveUser(UserVO userVO) {
        TUser user = new TUser();
        BeanUtils.copyProperties(userVO, user);
        if (!StringUtils.isEmpty(user.getId())) {
            if (null != userVO.getPhone()){
                UserDto userDto1 = userMapper.selectUserByOpenIdOrPhone(userVO);
                if (null != userDto1){
                    TUser olduser = new TUser();
                    olduser.setId(user.getId());
                    olduser = userMapper.selectOne(olduser);
                    if (null != olduser){
                        if (!olduser.getId().equals(userDto1.getId())){
                            return ResultVo.failure("10005","手机号已存在不能修改！");
                        }
                    }
                }
            }
           //修改
            user.setUpdateTime(new Date());
            userMapper.updateByPrimaryKeySelective(user);
        }else {
            UserDto userDto1 = userMapper.selectUserByOpenIdOrPhone(userVO);
            if (null != userDto1){
                return ResultVo.failure("10005","手机号已存在！");
            }
            //新增
            user.setCreateTime(new Date());
            user.setUserNo(UUID.randomUUID().toString().replace("-", "").substring(0, 16).toUpperCase());
            user.setId(UUID.randomUUID().toString().replace("-", ""));
            user.setInvitationCode(RandomStringUtils.randomAlphanumeric(6));
            user.setIsDel(0);
            try {
                user.setPassword(AesUtils.encrypt(AesUtils.DEFAULT_PWS,"abc1234"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            Integer courseId = userVO.getCourseId();
            if (courseId != null) {
                //直接生成已完成的订单
                UserDto userDto = new UserDto();
                BeanUtils.copyProperties(user,userDto);
                CourseBookedVO booked = new CourseBookedVO();
                BeanUtils.copyProperties(user,booked);
                booked.setSubType(3);
                booked.setCourseId(courseId.toString());
                booked.setType("course");
                ResultVo<CourseBookedDto> order = courseService.order(booked, userDto);
                if (!Objects.equals("200", order.getStatus())) {
                    //下单失败
                    return ResultVo.failure("10005", order.getMessage());
                }
            }
            userMapper.insertSelective(user);
        }
        UserDto result = new UserDto();
        BeanUtils.copyProperties(user,result);
        return ResultVo.success(result);
    }
}
